package com.owen.he.jee.service.impl;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import com.owen.he.jee.dao.ExportDao;
import com.owen.he.jee.model.Student;
import com.owen.he.jee.service.IndexService;
import com.owen.he.jee.service.exception.Assert;
import com.owen.he.jee.service.subService.ExcelExportService;
import com.owen.he.jee.service.subService.ExcelExportService.BatchExportInvoker;
import com.owen.he.jee.service.subService.ExcelExportService.DownloadFileInvoker;
import com.owen.he.jee.service.subService.ExcelExportService.DownloadStreamInvoker;
import com.owen.he.jee.service.subService.ExcelImportService;
import com.owen.he.jee.service.subService.ExcelImportService.ImportResultInvoker;
import com.owen.he.jee.utils.DateTimeUtils;
import com.owen.he.jee.utils.FileUtil;
import com.owen.he.jee.vo.excel.ImportExcelResult;

@Service
public class IndexServiceImpl implements IndexService{
	
	private static final Logger logger = LoggerFactory.getLogger(IndexServiceImpl.class);
	
	@Resource ExcelExportService excelExportService;
	@Resource ExportDao exportDao;
	@Resource ExcelImportService excelImportService;
	
	@Override
	public void downloadFile(final HttpServletResponse response,
			HttpServletRequest request) {
		
		final int initRowNumber = 1;
        final AtomicInteger rowNumber = new AtomicInteger(initRowNumber); /** 用于显示的行号 */
        //表示是否是最后一行
        final AtomicBoolean lastRow = new AtomicBoolean(false);
        Map<String, Object> map = new HashMap<String, Object>();
        List exprotStudentList = exportDao.exprotStudentList(map);
        Assert.notNull(exprotStudentList, "导出数据为空!");
		final Iterator datas = exprotStudentList.iterator();
    	excelExportService.doExport(Student.class, "student", new BatchExportInvoker() {
    		@Override
    		public Map<String, Object> next() {
    			Map<String, Object> rowDataMap = (Map<String, Object>) datas.next();
    			return rowDataMap;
    		}
    		
    		@Override
    		public boolean hasNext() {
    			boolean hasNextRow = datas.hasNext();
    			boolean notFirstRow = rowNumber.get() > initRowNumber;
    			if (hasNextRow == false && notFirstRow == true)
    				lastRow.set(true);
    			return hasNextRow || notFirstRow;
    		}
    	}, new DownloadFileInvoker() {
    		
    		@Override
    		public void invoke(String filePath) {
    			try {
    				//设置下载response的头消息信息
    				setResponseHeader(response, FileUtil.getFileName(filePath));
    				//处理IO流
    				InputStream in = new FileInputStream(filePath);
    				OutputStream out = response.getOutputStream();
    				byte[] b = new byte[2408];
    				int len;
    				while ((len = in.read(b))>0) {
    					out.write(b, 0, len);
    				}
    				//关闭流
    				out.close();
    				in.close();
    			} catch (Exception e) {
    				e.printStackTrace();
    			} finally {
    				FileUtil.deleteDirectory(filePath);
    			}
    		}
    	});
	}
	
	@Override
	public void downloadSteam(final HttpServletResponse response,
			HttpServletRequest request) {
		
		final int initRowNumber = 1;
        final AtomicInteger rowNumber = new AtomicInteger(initRowNumber); /** 用于显示的行号 */
        //表示是否是最后一行
        final AtomicBoolean lastRow = new AtomicBoolean(false);
        Map<String, Object> map = new HashMap<String, Object>();
        List exprotStudentList = exportDao.exprotStudentList(map);
        Assert.notNull(exprotStudentList, "导出数据为空!");
		final Iterator datas = exprotStudentList.iterator();
    	excelExportService.doExport(Student.class, "student", new BatchExportInvoker() {
    		@Override
    		public Map<String, Object> next() {
    			Map<String, Object> rowDataMap = (Map<String, Object>) datas.next();
    			return rowDataMap;
    		}
    		
    		@Override
    		public boolean hasNext() {
    			boolean hasNextRow = datas.hasNext();
    			boolean notFirstRow = rowNumber.get() > initRowNumber;
    			if (hasNextRow == false && notFirstRow == true)
    				lastRow.set(true);
    			return hasNextRow || notFirstRow;
    		}
    	}, new DownloadStreamInvoker() {
    		
    		@Override
    		public void invoke(SXSSFWorkbook workbook) {
    			try {
    				String nowTime = DateTimeUtils.changeDateToStr(new Timestamp(System.currentTimeMillis()));
    				//设置下载response的头消息信息
    				setResponseHeader(response, "student"+nowTime);
    				OutputStream out = response.getOutputStream();
    				workbook.write(out);
    				//关闭流
    				out.close();
    			} catch (Exception e) {
    				e.printStackTrace();
    			} 
    		}
    	});
	}

	private void setResponseHeader(HttpServletResponse response, String excelFileName) throws UnsupportedEncodingException {
		response.reset();
		response.setContentType("application/ms-excel;charset=gb2312");
		response.setHeader("Content-Disposition", "attachment; filename=\""
				+ new String(excelFileName.getBytes("gb2312"), "iso8859-1") + ".xls\"");
	}

	@Override
	public ImportExcelResult importExcel(MultipartFile file) {
		ImportExcelResult doImport = new ImportExcelResult();
		try {
			ImportResultInvoker importInvoker = new ImportResultInvoker() {
				
				@Override
				public ImportExcelResult invokerResult(Object obj) {
					ImportExcelResult res = new ImportExcelResult();
					Map<String,Object> msg = new HashMap<>();
					try {
						Student s = (Student) obj;
						if(s==null) {
							msg.put("error", "对象为空！");
							res.setRecordIsOk(false);
							return res;
						}
						//校验对象
						if(vaildObj(res, msg, s)){
							//入库操作
							exportDao.saveStudent(s);
							res.setRecordIsOk(true);
						}else{
							res.setRecordIsOk(false);
						}
					} catch (Exception e) {
						msg.put("error", e.getMessage());
						res.setRecordIsOk(false);
						e.printStackTrace();
					}
					res.setMesageResult(msg);
					return res;
				}
			};
			
			doImport = excelImportService.doImport(file.getInputStream(), importInvoker, Student.class);
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		return doImport;
	}

	protected boolean vaildObj(ImportExcelResult res, Map<String, Object> msg,
			Student s) {
		if(StringUtils.isNoneBlank(s.getAge())) {
			int age = Integer.parseInt(s.getAge());
			boolean isAge = age>18&&age<50;
			if(!isAge) {
				msg.put("error", "年龄不在范围内！");
				return false;
				//throw new ServiceException("年龄不在范围内");
			}
		}else{
			msg.put("error", "年龄不能为空！");
			return false;
			//throw new ServiceException("年龄不能为空！");
		}
		
		if(StringUtils.isNoneBlank(s.getSex())) {
			Map<String, String> sexMap = sexMap();
			boolean f = false;
			for (String key : sexMap.keySet()) {
				if(s.getSex().equals(key)) {
					s.setSex(sexMap.get(key));
					f = true;
				}
			}
			if(!f) {
				msg.put("error", "请输入正确的性别");
				return false;
			}
			
		}else{
			msg.put("error", "性别不能为空");
			return false;
			//throw new ServiceException("性别不能为空");
		}
		
		if(StringUtils.isBlank(s.getName())) {
			msg.put("error", "名字不能为空");
			return false;
			//throw new ServiceException("名字不能为空");
		}
		return true;
	}
	
	public Map sexMap() {
		Map<String, String> map = new HashMap<>();
		map.put("男", "1");
		map.put("女", "0");
		return map;
	}

	@Override
	public List<Map> resultData(String skey, String columnsSql) {
		return exportDao.yjResultData(columnsSql);
	}
	
}
